#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <termios.h> // 用于密码隐藏输入

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024

// 隐藏输入的回显（用于密码输入）
void disableEcho() {
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}

// 恢复输入的回显
void enableEcho() {
    struct termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag |= ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}

// 序列化字符串（长度前缀法）
int serialize_string(const char* str, uint8_t* buffer, size_t buffer_size) {
    size_t len = strlen(str);
    if (len + 1 > buffer_size) {
        return -1; // 缓冲区太小
    }
    
    // 先写入字符串长度
    uint32_t net_len = htonl((uint32_t)len);
    memcpy(buffer, &net_len, sizeof(net_len));
    
    // 再写入字符串内容
    memcpy(buffer + sizeof(net_len), str, len);
    
    return sizeof(net_len) + len;
}

// 从用户获取输入
int get_input(const char* prompt, char* buffer, size_t buffer_size, int is_password) {
    printf("%s", prompt);
    fflush(stdout);
    
    if (is_password) {
        disableEcho();
    }
    
    if (fgets(buffer, buffer_size, stdin) == NULL) {
        if (is_password) {
            enableEcho();
        }
        return -1;
    }
    
    // 移除换行符
    buffer[strcspn(buffer, "\n")] = '\0';
    
    if (is_password) {
        enableEcho();
        printf("\n");
    }
    
    return 0;
}

// 连接到服务器
int connect_to_server() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket creation failed");
        return -1;
    }
    
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("invalid address");
        close(sock);
        return -1;
    }
    
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connection failed");
        close(sock);
        return -1;
    }
    
    return sock;
}

// 发送登录请求
int send_login_request(int sock, const char* username, const char* password) {
    uint8_t buffer[BUFFER_SIZE];
    int offset = 0;
    
    // 序列化用户名
    int username_len = serialize_string(username, buffer + offset, BUFFER_SIZE - offset);
    if (username_len < 0) {
        printf("用户名太长\n");
        return -1;
    }
    offset += username_len;
    
    // 序列化密码
    int password_len = serialize_string(password, buffer + offset, BUFFER_SIZE - offset);
    if (password_len < 0) {
        printf("密码太长\n");
        return -1;
    }
    offset += password_len;
    
    // 发送数据
    if (send(sock, buffer, offset, 0) < 0) {
        perror("发送失败");
        return -1;
    }
    
    return 0;
}

// 接收服务器响应
int receive_response(int sock) {
    uint8_t buffer[BUFFER_SIZE];
    int bytes_received = recv(sock, buffer, BUFFER_SIZE, 0);
    
    if (bytes_received < 0) {
        perror("接收失败");
        return -1;
    } else if (bytes_received == 0) {
        printf("服务器关闭了连接\n");
        return -1;
    }
    
    // 解析响应（假设服务器返回一个字节：1表示成功，0表示失败）
    if (bytes_received >= 1) {
        return buffer[0];
    }
    
    return -1;
}

int main() {
    char username[256];
    char password[256];
    
    // 获取用户名和密码
    if (get_input("用户名: ", username, sizeof(username), 0) < 0) {
        printf("获取用户名失败\n");
        return 1;
    }
    
    if (get_input("密码: ", password, sizeof(password), 1) < 0) {
        printf("获取密码失败\n");
        return 1;
    }
    
    // 连接到服务器
    int sock = connect_to_server();
    if (sock < 0) {
        return 1;
    }
    
    printf("正在连接到服务器...\n");
    
    // 发送登录请求
    if (send_login_request(sock, username, password) < 0) {
        close(sock);
        return 1;
    }
    
    printf("正在验证登录信息...\n");
    
    // 接收服务器响应
    int result = receive_response(sock);
    if (result < 0) {
        close(sock);
        return 1;
    }
    
    // 处理响应
    if (result == 1) {
        printf("登录成功！\n");
        // 这里可以添加登录成功后的操作
    } else {
        printf("登录失败：用户名或密码错误\n");
    }
    
    close(sock);
    return 0;
}